Reducing Warnings - Safe Integral Comparisons#960
Conversation
rcsanchez97
left a comment
There was a problem hiding this comment.
I have made some suggested changes based on what appear to be missing unsigned specifiers. Though, I may be mistaken so I am going to go ahead and approve the PR and leave it up to you to decide whether my suggestions are appropriate.
src/libbson/tests/test-bson-cmp.c
Outdated
| BSON_ASSERT (!bson_cmp_less_ss (1, -1)); | ||
| BSON_ASSERT (!bson_cmp_less_ss (1, 1)); | ||
|
|
||
| BSON_ASSERT (!bson_cmp_less_uu (0u, 0)); |
There was a problem hiding this comment.
| BSON_ASSERT (!bson_cmp_less_uu (0u, 0)); | |
| BSON_ASSERT (!bson_cmp_less_uu (0u, 0u)); |
src/libbson/tests/test-bson-cmp.c
Outdated
| BSON_ASSERT (bson_cmp_greater_ss (1, -1)); | ||
| BSON_ASSERT (!bson_cmp_greater_ss (1, 1)); | ||
|
|
||
| BSON_ASSERT (!bson_cmp_greater_uu (0u, 0)); |
There was a problem hiding this comment.
| BSON_ASSERT (!bson_cmp_greater_uu (0u, 0)); | |
| BSON_ASSERT (!bson_cmp_greater_uu (0u, 0u)); |
src/libbson/tests/test-bson-cmp.c
Outdated
| BSON_ASSERT (!bson_cmp_less_equal_ss (1, -1)); | ||
| BSON_ASSERT (bson_cmp_less_equal_ss (1, 1)); | ||
|
|
||
| BSON_ASSERT (bson_cmp_less_equal_uu (0u, 0)); |
There was a problem hiding this comment.
| BSON_ASSERT (bson_cmp_less_equal_uu (0u, 0)); | |
| BSON_ASSERT (bson_cmp_less_equal_uu (0u, 0u)); |
src/libbson/tests/test-bson-cmp.c
Outdated
| BSON_ASSERT (bson_cmp_greater_equal_ss (1, -1)); | ||
| BSON_ASSERT (bson_cmp_greater_equal_ss (1, 1)); | ||
|
|
||
| BSON_ASSERT (bson_cmp_greater_equal_uu (0u, 0)); |
There was a problem hiding this comment.
| BSON_ASSERT (bson_cmp_greater_equal_uu (0u, 0)); | |
| BSON_ASSERT (bson_cmp_greater_equal_uu (0u, 0u)); |
|
|
||
| BSON_ASSERT (bson_in_range_unsigned (int32_t, 0u)); | ||
| BSON_ASSERT (bson_in_range_unsigned (int32_t, (uint64_t) int32_max)); | ||
| BSON_ASSERT (!bson_in_range_unsigned (int32_t, (uint64_t) (int32_max + 1))); |
There was a problem hiding this comment.
| BSON_ASSERT (!bson_in_range_unsigned (int32_t, (uint64_t) (int32_max + 1))); | |
| BSON_ASSERT (!bson_in_range_unsigned (int32_t, (uint64_t) (int32_max + 1u))); |
There was a problem hiding this comment.
int32_max is an int64_t (signed), so a signed integer literal is appropriate here.
eramongodb
left a comment
There was a problem hiding this comment.
Passing 0 to unsigned parameter is benign since 0 is guaranteed to be representable regardless of signedness, but for consistency, I agree it would be good to update the literals with unsigned suffixes. (Hurray for copy-paste errors...)
|
|
||
| BSON_ASSERT (bson_in_range_unsigned (int32_t, 0u)); | ||
| BSON_ASSERT (bson_in_range_unsigned (int32_t, (uint64_t) int32_max)); | ||
| BSON_ASSERT (!bson_in_range_unsigned (int32_t, (uint64_t) (int32_max + 1))); |
There was a problem hiding this comment.
int32_max is an int64_t (signed), so a signed integer literal is appropriate here.
kevinAlbs
left a comment
There was a problem hiding this comment.
LGTM. Nicely done. I think bson-cmp.h is going to be useful. I have two comments, but nothing to block merge.
src/libbson/src/bson/bson-cmp.h
Outdated
| return bson_cmp_greater_equal_uu (value, 0u) && \ | ||
| bson_cmp_less_equal_uu (value, max); \ |
There was a problem hiding this comment.
| return bson_cmp_greater_equal_uu (value, 0u) && \ | |
| bson_cmp_less_equal_uu (value, max); \ | |
| return bson_cmp_less_equal_uu (value, max); \ |
| BSON_ASSERT (!bson_in_range_signed (int8_t, int8_max + 1)); | ||
|
|
||
| BSON_ASSERT (bson_in_range_unsigned (int8_t, 0u)); | ||
| BSON_ASSERT (bson_in_range_unsigned (int8_t, (uint64_t) int8_max)); |
There was a problem hiding this comment.
Suggest removing unnecessary cast to uint64_t for consistency with other calls. Here and below.
There was a problem hiding this comment.
These casts are necesary, as the intN_min and intN_max variables are signed integers. Without the casts, the arguments will produce implicit sign conversion warnings from int64_t to uint64_t.
This is part of a series of PRs intended to reduce the set of warnings currently being observed when building the C driver.
This PR introduces a set of utilities modeled after the Safe Integral Comparisons proposal for the C++ standard library, which was accepted and merged into the C++20 standard. These utilities are extremely useful in addressing warnings involving comparisons or conversions between integers with different signedness and sizes.
The interface proposed in the original paper relies on type deduction to select appropriate behavior according to the signedness and size of the given arguments:
As C does not have type deduction required to support this interface, two major compromises are made instead:
int64_toruint64_tas specified by (1) before further analysis.Therefore, the equivalent code to the above example given
A = int16_tandB = uint32_tlooks like the following:where the
_susuffix indicatesais signed andbis unsigned.The set of supported types is also limited to the following:
ssize_tandsize_t.More types may be added if needed, so long as for the given type
T,sizeof (T) <= sizeof (uint64_t)is true and its representable range is known and defined with corresponding*_MINand*_MAXmacros.To support the
std::in_rangeset of functions even on C90 (where the necessary<limits.h>and<stdint.h>macros may not be defined), the corresponding set of numeric limit macros have been added to bson-compat.h, including those forssize_t(note:SSIZE_MINis normally not defined even by the POSIX standard). The preprocessor block conditioned on!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901Lmay be removed once the minimum C standard for the C driver is bumped to C99 or newer.